#include "CameraHandler.h"

CameraHandler::CameraHandler()
{
}

CameraHandler::~CameraHandler(){}


int CameraHandler::view = 0;

void CameraHandler::Init()
{
    larg = LARG_SCR;
    alt = ALT_SCR;
    
    //posizione occhio
    view = 4;
    ChangeView();
 
    noflyzone = false;
}

void CameraHandler::Move()
{
    if(noflyzone)
       {
             
            glEnable(GL_COLOR_MATERIAL);
            glColor3f(1,0,0);     
            glRasterPos3f(-15,8,0);
            for (char *c=NO_FLY_ZONE_STRING; *c != '\0'; c++) 
               glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);

         glDisable(GL_COLOR_MATERIAL);
            
        } 
          


    //effettuo la rotazione della scena
    glRotatef(state->cam_angY, 0, 1, 0);
        
    //posiziono la scena
    glTranslated(state->cam_posX,state->cam_posY ,state->cam_posZ);
}

void CameraHandler::ChangeView(){
    
    view++;
    if (view == 6) view = 0;
    
    eyeX = CAM_EYE[view][0], 
    eyeY = CAM_EYE[view][1], 
    eyeZ = CAM_EYE[view][2];
    
    if (view == 5){
     state->map->visible = true;
     state->fotoid->visible = true;}
    else{
     state->map->visible = false;
     state->fotoid->visible = false;}
    
    
    
    Move_View();
    glutPostRedisplay();
   
}

void CameraHandler::ResizeView(int l ,int a){
 
    larg = l;
    alt = a;
    
    if(state->motionblur)
       {
        glClearAccum(0.0, 0.0, 0.0, 1.0);
        glClear(GL_ACCUM_BUFFER_BIT);
       }
    glViewport(0,0,l,a);
    Move_View();
    glutPostRedisplay();
}

void CameraHandler::Camera_Mouse_Mov(int xo, int yo,int x,int y)
{
  if (state->rightbuttondown)
  {
    if (x > xo)       eyeX+=2;
    else if (x < xo)  eyeX-=2;
    
    if (y > yo)       eyeZ+=2;
    else if (y < yo)  eyeZ-=2;
  }
  else if (state->leftbuttondown)
  {
    if (y > yo)       eyeY+=2;
    else if (y < yo)  eyeY-=2;
  }


state->map->visible = false;
state->fotoid->visible = false;
view = 4;
Move_View();
glutPostRedisplay();
}

void CameraHandler::Move_View()
{
 //sposto la vista    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(VIS_ANGLE,((GLfloat)larg/(GLfloat)alt)* ASPECT_RATIO,0.1,PROF_SCR);
    gluLookAt(eyeX,eyeY,eyeZ, 0,0,0, 0,1,0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


void CameraHandler::DoIdle_Start_Pos()
{
  bool flag = false;
    
  if (step_counter < FAR_STEP)
  {
     eyeX -= InitCamPosAdder[0]; 
     eyeZ -= InitCamPosAdder[2];
     eyeY -= InitCamPosAdder[1];
     step_counter++;
     state->motionblur = true;
  }
  else flag = true;
  
  
  if (flag)
     {
        state->motionblur = false;
        state->camera_pos = false;
        view = 4;
        ChangeView(); 
     } 
  
  
  Move_View();
 }

void CameraHandler::DoIdle()
{
  
       
    //calcolo l'anglo di rotazione della camera
    if (state->rotating != 0)
         state->cam_angY = state->cam_angY + state->rotating * 1;
    
    //spostamento verticale della camera(segue il terreno)
    if (state->takeoff)
    {
      if (state->cam_posY < state->cam_fut_posY - 1) state->cam_posY += MAX_INC_ALT; 
      else if (state->cam_posY > state->cam_fut_posY + 1) state->cam_posY -= MAX_INC_ALT;    
    }
    
    
    if (state->translating != 0)
    {
      switch (state->translating)
      {
         case  1:  MvLeft(-1);   break;
         case  2:  MvLeft(1);   break;
         case  3:  if(state->fly_height < 200)state->fly_height += 0.7;   break;
         case  4:  if(state->fly_height > 10)state->fly_height -= 0.7;   break;
       }
    }
        
    //muovo l'elicottero  
    if (state->moving == 1)
    {
        //traslo la telecamera dietro l'elicottero
        dx = sin(state->cam_angY * PI_DIV_180);   //direzione pesata
        dz = -cos(state->cam_angY * PI_DIV_180);   //direzione pesata
        
        //controllo che l'elicottero sia nella fly zone
        state->cam_posX -= dx * COP_VEL;
        state->cam_posZ -= dz * COP_VEL;
        
   
       if(!Fly_Zone_Control())
       {
        state->moving = false;      
        state->cam_posX += dx * COP_VEL;
        state->cam_posZ += dz * COP_VEL;
       }     
    } 
    
    
 
  if (earthquake)
  {
    factQ -= 0.01;
    angQ += 2;
    float qx =  sin(angQ)* factQ; 
    float qy =  cos(angQ)* factQ;
    float qz =  sin(angQ + 90)* factQ;
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(VIS_ANGLE,((GLfloat)larg/(GLfloat)alt)* ASPECT_RATIO,0.1,PROF_SCR);
    gluLookAt(eyeX + qx ,eyeY + qy ,eyeZ + qz , 0,0,0, 0,1,0);
    glMatrixMode(GL_MODELVIEW);

   
    if(factQ <= 0) 
    {
        if (noflyzone) noflyzone = false;
        earthquake = false;
    }
  }
}

void CameraHandler::Camera_Earthquake()
{
      
    factQ = 0.5;
    angQ = -45;
    earthquake = true;
}

void CameraHandler::Camera_Fullscreen()
{
    if(state->schermo_intero==0) {
        glutFullScreen();
        state->schermo_intero=1;
    }
    else {
        glutReshapeWindow(LARG_SCR,ALT_SCR);
        state->schermo_intero=0;
    }
    Move_View();
    glutPostRedisplay();

}

void CameraHandler::MvLeft(int i)
{
   float dx = sin(state->cam_angY * PI_DIV_180);   //direzione pesata
   float dz = cos(state->cam_angY * PI_DIV_180);   //direzione pesata
   
   state->cam_posX -= dz * i;
   state->cam_posZ -= dx * i;
   
   if(!Fly_Zone_Control())
       {
        state->translating = false;      
        state->cam_posX += dz * i;
        state->cam_posZ += dx * i;
       }     
       
   glutPostRedisplay();
}

void CameraHandler::Save()
{
 old_view = view;
 Oldeye[0] = eyeX;
 Oldeye[1] = eyeY;
 Oldeye[2] = eyeZ;
 view = 4;
 ChangeView();

}

void CameraHandler::Restore()
{
 view = old_view; 
 eyeX = Oldeye[0];
 eyeY = Oldeye[1];
 eyeZ = Oldeye[2]; 
 
 if (view == 5){
     state->map->visible = true;
     state->fotoid->visible = true;}
 else{
     state->map->visible = false;
     state->fotoid->visible = false;}
 
 Move_View();

}

void CameraHandler::SelFarPos()
{
    step_counter = 0;
    state->map->visible = false;
    state->fotoid->visible = false;

    InitCamPos[0] = eyeX;
    InitCamPos[1] = eyeY;
    InitCamPos[2] = eyeZ;
    eyeX = rand() % MAX_EYE_FARXZ;
    eyeY = MAX_EYE_FARY + rand() % 50;
    eyeZ = rand() % MAX_EYE_FARXZ;
    
    InitCamPosAdder[0] = (eyeX - InitCamPos[0])/FAR_STEP; 
    InitCamPosAdder[1] = (eyeY - InitCamPos[1])/FAR_STEP;
    InitCamPosAdder[2] = (eyeZ - InitCamPos[2])/FAR_STEP;
    
    Move_View();
}


bool CameraHandler::Fly_Zone_Control()
{
     int dist = (int)sqrt((state->cam_posX * state->cam_posX ) + (state->cam_posZ*state->cam_posZ));
        if(dist > FLY_ZONE_DIST)
        {
           //printf("No fly zone");
           if (earthquake == false)
           {     
            Camera_Earthquake();
            Camera_NoFlyZone();
            state->fotoid->SetFotoMal();  
           }
   
          return false;
        }
return true;
}

void CameraHandler::MotionBlur()
{

    if(state->motionblur)
       {
         glAccum(GL_MULT, state->blurfactor);
         glAccum(GL_ACCUM, 1-state->blurfactor);
         glAccum(GL_RETURN, 1.0);
       }
       
}       

void CameraHandler::ChangeMotionBlur()
{
   if (state->motionblur == false)
    { 
      state->motionblur = true;
      glClearAccum(0.0, 0.0, 0.0, 1.0);
      glClear(GL_ACCUM_BUFFER_BIT);
      state->blurfactor = 0.78;
    }
   else    state->motionblur = false;
   
      
}   
